/*
 * ListBox.cpp
 */

#include "ListBox.h"
#include "TextBox.h"
#include "SDL_gfxPrimitives.h"

ListBox::ListBoxRow::ListBoxRow(Uint16 width, Uint16 height, const std::string& text)
{
	this->selected = false;
	this->selectedRow = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0, 0, 0, 0);
	this->unselectedRow = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0, 0, 0, 0);
	if (this->selectedRow == NULL || this->unselectedRow == NULL)
		throw SDL_Exception("LISTROW - SDL CREATE RGB SURFACE - ERROR");
	TextBox txtBox(0, 0, width, height, text);
	txtBox.setEnabled(false);
	txtBox.show();
	txtBox.setSelected(false);
	txtBox.draw(this->unselectedRow);
	txtBox.setSelected(true);
	txtBox.draw(this->selectedRow);
}

ListBox::ListBoxRow::~ListBoxRow()
{
	SDL_FreeSurface(this->selectedRow);
	SDL_FreeSurface(this->unselectedRow);
}

void ListBox::ListBoxRow::draw(SDL_Surface* screenDst, const SDL_Rect& dstRect)
{
	SDL_Rect destRect = dstRect;
	if(SDL_BlitSurface( (getSelected()) ? selectedRow : unselectedRow, NULL,
			screenDst, &destRect) < 0)
		throw SDL_Exception("LISTBOXROW - BLIT SURFACE - ERROR");
}

ListBox::ListBox() : Component (0, 0, 8 * SCROLL_WIDTH, 2 * LISTBOXROW_HEIGHT)
{
	this->init();
}

ListBox::ListBox(Sint16 posX, Sint16 posY, Uint16 width, Uint16 height)
:Component (posX, posY, width, height)
{
	this->init();
}

ListBox::ListBox(Sint16 posX, Sint16 posY, Uint16 width, Uint16 height,
		const std::vector<std::string>& defaultValues)
:Component (posX, posY, width, height)
{
	this->init();
	std::vector<std::string>::const_iterator it;
	for (it = defaultValues.begin(); it != defaultValues.end(); ++it)
		this->rows.push_back(new ListBoxRow(width, LISTBOXROW_HEIGHT, *it));
}

ListBox::~ListBox()
{
	cleanUp();
}

void ListBox::init()
{
	this->listSurface = NULL;
}

void ListBox::cleanUp()
{
	std::vector<ListBoxRow*>::iterator itRows;
	for (itRows = this->rows.begin(); itRows != this->rows.end(); ++itRows)
		delete *itRows;
	this->rows.clear();
	if (this->listSurface != NULL)
	{
		SDL_FreeSurface(this->listSurface);
		this->listSurface = NULL;
	}
}

void ListBox::show()
{
	if (this->listSurface != NULL)
		SDL_FreeSurface(this->listSurface);

	Uint16 listHeight = this->rows.size() * LISTBOXROW_HEIGHT;
	this->listSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, getWidth(), listHeight, 32, 0, 0, 0, 0);
	if (this->listSurface == NULL)
		throw SDL_Exception("LISTBOX - CREATE_RGB_SURFACE - ERROR");

	this->widgetFreezeArea = getWidgetArea();

	this->widgetVisibleArea.h = getHeight();
	this->widgetVisibleArea.w = getWidth();
	this->widgetVisibleArea.x = 0;
	this->widgetVisibleArea.y = 0;  // Variable desplazable por vertical scroll

	SDL_Rect rowSrcArea;
	rowSrcArea.h = listHeight;
	rowSrcArea.w = getWidth();
	rowSrcArea.x = 0;
	rowSrcArea.y = 0;

	std::vector<ListBoxRow*>::iterator itRows;
	for (itRows = this->rows.begin(); itRows != this->rows.end(); ++itRows)
	{
		(*itRows)->draw(this->listSurface, rowSrcArea);
		rowSrcArea.y += LISTBOXROW_HEIGHT;
	}
	this->setShow(true);
}

void ListBox::draw(SDL_Surface* screen)
{
	this->drawList(screen);
	this->drawVScroll(screen);
}

void ListBox::drawList(SDL_Surface* s)
{
	SDL_Rect srcRect = this->widgetVisibleArea;
	SDL_Rect destRect = this->widgetFreezeArea;
	if (SDL_BlitSurface( this->listSurface, &srcRect, s, &destRect) < 0)
		throw SDL_Exception("LISTBOX - BLIT SURFACE - ERROR");
}

void ListBox::drawVScroll(SDL_Surface* s)
{
	if (this->listSurface->clip_rect.h > this->widgetFreezeArea.h)
	{
		SDL_Rect destArea = this->widgetFreezeArea;
		destArea.x += destArea.w - SCROLL_WIDTH;
		destArea.w = SCROLL_WIDTH;
		if(SDL_FillRect( s, &destArea, DARK_GREY) < 0)
			throw SDL_Exception("LISTBOX - SDL FILL RECT - ERROR");
		if(boxRGBA( s, destArea.x, destArea.y, destArea.x + SCROLL_WIDTH,
				destArea.y + SCROLL_WIDTH, 128, 128, 128, 255) < 0)
			throw SDL_Exception("LISTBOX - SDL BOX RGBA - ERROR");
		if(boxRGBA( s, destArea.x, destArea.y + destArea.h - SCROLL_WIDTH,
				destArea.x + SCROLL_WIDTH, destArea.y + destArea.h,
				128, 128, 128, 255) < 0)
			throw SDL_Exception("LISTBOX - SDL BOX RGBA - ERROR");
		if (filledTrigonRGBA(s, destArea.x + SCROLL_WIDTH * 0.25, destArea.y + SCROLL_WIDTH * 0.75,
				destArea.x + SCROLL_WIDTH * 0.75, destArea.y + SCROLL_WIDTH * 0.75,
				destArea.x + SCROLL_WIDTH * 0.50, destArea.y + SCROLL_WIDTH * 0.25,
				255, 255, 255, 255) < 0)
			throw SDL_Exception("LISTBOX - SDL FILL TRIGON RGBA - ERROR");
		if (filledTrigonRGBA(s, destArea.x + SCROLL_WIDTH * 0.25, destArea.y + destArea.h - SCROLL_WIDTH * 0.75,
				destArea.x + SCROLL_WIDTH * 0.75, destArea.y + destArea.h - SCROLL_WIDTH * 0.75,
				destArea.x + SCROLL_WIDTH * 0.50, destArea.y + destArea.h - SCROLL_WIDTH * 0.25,
				255, 255, 255, 255) < 0)
			throw SDL_Exception("LISTBOX - SDL FILL TRIGON RGBA - ERROR");
	}
}

void ListBox::handleEvent(SDL_Event* event)
{
/*
	//Si se presiono el boton izquierdo del mouse
	if(event->type == SDL_MOUSEBUTTONDOWN && event->button.button == SDL_BUTTON_LEFT)
	{
		if (this->ocurredInside(event->button.x, event->button.y))
		{
//			if (event->button.x > this->widgetFreezeArea.x + this->widgetFreezeArea.w - SCROLL_WIDTH)
		}
	}
	//Si se presiono una tecla del teclado y se encontraba activa la textbox
	else if(this->selected && this->isEnabled() && event->type == SDL_KEYDOWN)
	{
		//Si el caracter es valido para mostrar, lo agrego (32 < ASCII < 122)
		if(event->key.keysym.sym >= SDLK_SPACE && event->key.keysym.sym <= SDLK_z)
		{
			//Append the character
			this->showText.insert(this->stringPosCursor++,
					std::string(1, (char)event->key.keysym.unicode));
			// Flag Cursor Moved
			this->cursorMoved = true;
			// Flag Text Changed
			this->textChanged = true;
		}
		else if (!this->showText.empty()) {
			if( event->key.keysym.sym == SDLK_BACKSPACE && this->stringPosCursor > 0)
			{
				//Remove the corresponding character
				this->showText.erase(--this->stringPosCursor, 1);
				// Flag Cursor Moved
				this->cursorMoved = true;
				// Flag Text Changed
				this->textChanged = true;
			}
			else if( event->key.keysym.sym == SDLK_DELETE && this->stringPosCursor < this->showText.length())
			{
				//Remove the corresponding character
				this->showText.erase(this->stringPosCursor, 1);
				// Flag Text Changed
				this->textChanged = true;
			}
			else if( event->key.keysym.sym == SDLK_LEFT && this->stringPosCursor > 0 )
			{
				// Moves the cursor to the left
				--this->stringPosCursor;
				// Restart the blinking cycle
				this->cursorTimer.start();
				// Flag Cursor Moved
				this->cursorMoved = true;
			}
			else if( event->key.keysym.sym == SDLK_RIGHT && this->stringPosCursor < this->showText.length() )
			{
				// Moves the cursor to the right
				++this->stringPosCursor;
				// Restart the blinking cycle
				this->cursorTimer.start();
				// Flag Cursor Moved
				this->cursorMoved = true;
			}
		}
	}
*/
}
